package com.qf.controller.advice;/*
 *徐韬
 *2021/11/3
 *15:01
 */

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qf.annotation.ignoreLog;
import com.qf.annotation.logAnnoTation;
import com.qf.pojo.LogBean;
import com.qf.pojo.MyAuthUser;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import sun.reflect.generics.tree.MethodTypeSignature;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class logAdvice {
    public ObjectMapper objectMapper;

    @Autowired
    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    /**
     * 定点切入表达式 ->方法的全限定名称的类似于正则的写法
     * 修饰符 返回值 包类 方法名(参数) 异常
     * public void com.qf..controller.*controller.*(..)
     */
    @Pointcut("execution(* com.qf.controller.*Controller.*(..))")
    public void PointCut() {
    }

    @Around("PointCut()")
    public Object processLog(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Object target = joinPoint.getTarget();//获取到当前方法所以在的类对象
        Method method = signature.getMethod();//正在执行的方法

        //获取类上的自定义注解 目的是为了知道当前是什么操作
        Object proceed = null;//放行获取到的原始结果

            proceed = joinPoint.proceed();

        Annotation ignoreLog = method.getAnnotation(ignoreLog.class);
        if (ignoreLog != null) {
            return proceed; //如果采用这个注解 就直接返回结果  后面的日志就不运行了
        }

        LogBean tlogben = new LogBean();//记录日志的对象
        logAnnoTation anno = method.getAnnotation(logAnnoTation.class);
        if (anno != null) {
            String value = anno.value(); //获取注解的介绍
            tlogben.setOper(value);//记录用户正在操作
        }
        tlogben.setAccessData(new Date());//记录用户操作的时间


        String[] parameterNames = signature.getParameterNames();//获取方法中的参数名
        Object[] args = joinPoint.getArgs();//获取传递的参数
        if (parameterNames != null) {   //将参数的值组合起来放到map中
            Map map = new HashMap();
            for (int i = 0; i < parameterNames.length; i++) {
                String parameterName = parameterNames[i];//获取每个参数的名字
                Object arg = args[i];//获取传递的参数 可能是一个对象
                map.put(parameterName, arg);
            }
            //将参数保存到对象中
            tlogben.setParam(objectMapper.writeValueAsString(map));
        }

        MyAuthUser principal = (MyAuthUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (principal != null) {
            Long id = principal.getId();
            tlogben.setUserId(id);//传递访问者的id
        }

        //将结果 返回保存
        tlogben.setResult(objectMapper.writeValueAsString(proceed));
        System.err.println(tlogben);
        return proceed;
    }
}
